#ifndef _SEQ_LIST_H_
#define _SEQ_LIST_H_

#include "List.h"
#include "Exception.h"

namespace MySTL
{

template < typename T >
class SeqList : public List<T>
{
public:
	SeqList();
	~SeqList();
	bool insert(int n, const T& value);
	bool insert(const T& value);
	bool remove(int n);
	bool get(int n, T& value) const;
	T& get(int n);
	const T& get(int n) const;
	bool set(int n, const T& value);
	int length() const;
	int find(const T& value) const;
	void clear();

	T& operator [](int n);
	const T& operator [](int n) const;

	virtual int capacity() const = 0;

protected:
	T* m_array;
	int m_length;
};

template < typename T >
SeqList<T>::SeqList()
{
	m_array = NULL;
	m_length = 0;
}

template < typename T >
SeqList<T>::~SeqList()
{
	clear();
}

template < typename T >
bool SeqList<T>::insert(int n, const T& value)
{
	bool ret = (n >= 0) && (n <= m_length) && (m_length < capacity());

	if (ret)
	{
		for (int i = m_length; i > n; --i)
		{
			m_array[i] = m_array[i - 1];
		}

		++m_length;
		m_array[n] = value;
	}

	return ret;
}

template < typename T >
bool SeqList<T>::insert(const T& value)
{
	return insert(m_length, value);
}

template < typename T >
bool SeqList<T>::remove(int n)
{
	bool ret = (n >= 0) && (n < m_length);

	if (ret)
	{
		for (int i = n; i < m_length; ++i)
		{
			m_array[i] = m_array[i + 1];
		}

		--m_length;
	}

	return ret;
}

template < typename T >
bool SeqList<T>::get(int n, T& value) const
{
	bool ret = (n >= 0) && (n < m_length);

	if (ret)
	{
		value = m_array[n];
	}

	return ret;
}

template < typename T >
T& SeqList<T>::get(int n)
{
	if ((n >= 0) && (n < m_length))
	{
		return m_array[n];
	}
	else
	{
		THROW_EXCEPTION(IndexOutOfBoundsException, "Index out of bounds in SeqList<T>::get(int n)");
	}
}

template < typename T >
const T& SeqList<T>::get(int n) const
{
	return const_cast<SeqList<T>*>(this)->get(n);
}

template < typename T >
bool SeqList<T>::set(int n, const T& value)
{
	bool ret = (n >= 0) && (n < m_length);

	if (ret)
	{
		m_array[n] = value;
	}

	return ret;
}

template < typename T >
int SeqList<T>::length() const
{
	return m_length;
}

template < typename T >
int SeqList<T>::find(const T& value) const
{
	int ret = -1;

	for (int i = 0; i < m_length; ++i)
	{
		if (m_array[i] == value)
		{
			ret = i;
			break;
		}
	}

	return ret;
}

template < typename T >
void SeqList<T>::clear()
{
	m_length = 0;
}

template < typename T >
T& SeqList<T>::operator [](int n)
{
	if ((n >= 0) && (n < m_length))
	{
		return m_array[n];
	}
	else
	{
		THROW_EXCEPTION(IndexOutOfBoundsException, "Index out of bounds in T& SeqList<T>::operator [](int n)");
	}
}

template < typename T >
const T& SeqList<T>::operator [](int n) const
{
	return const_cast<SeqList<T>&>(*this)[n];
}

}

#endif